1 <?xml version=
"1.0" encoding=
"utf-8" ?>
2 <!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN"
3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4 <html xmlns=
"http://www.w3.org/1999/xhtml">
6 <title>Metaobject Protocols
</title>
7 <meta name=
"generator" content=
"muse.el" />
8 <meta http-equiv=
"Content-Type"
9 content=
"text/html; charset=utf-8" />
11 content=
"width=device-width, initial-scale=1.0" />
12 <link href=
"https://feeds.unknownlamer.org/rss/site-updates"
13 rel=
"alternate" type=
"application/rss+xml" title=
"Updates Feed" />
15 <link rel=
"stylesheet" href=
"default.css" />
18 <h1>Metaobject Protocols
</h1>
19 <div class=
"contents">
22 <a href=
"#sec1">Background
</a>
27 <a href=
"#sec2">Object Protocols
</a>
30 <a href=
"#sec3">CLOS Way of OO
</a>
35 <a href=
"#sec4">Classes for Scratch Data and Types
</a>
38 <a href=
"#sec5">Generics with Methods that Implement Protocols
</a>
45 <a href=
"#sec6">Limitations of Default Language Behavior
</a>
50 <a href=
"#sec7">Slot Storage
</a>
53 <a href=
"#sec8">Design Patterns
</a>
58 <a href=
"#sec9">Metasoftware
</a>
63 <a href=
"#sec10">Runtime Generated Classes
</a>
66 <a href=
"#sec11">Object Inspection
</a>
71 <a href=
"#sec12">Metaobject Protocols
</a>
76 <a href=
"#sec13">Limited/Generalized Internals of the Implementation
</a>
79 <a href=
"#sec14">Classes of MOPs
</a>
84 <a href=
"#sec15">Reflective
</a>
87 <a href=
"#sec16">Intercessory
</a>
92 <a href=
"#sec17">Violation of Encapsulation?
</a>
97 <a href=
"#sec18">MOP Design Principles
</a>
102 <a href=
"#sec19">Layered Protocol
</a>
107 <a href=
"#sec20">Top Level
<strong>Must
</strong> Call Lower Level Methods
</a>
110 <a href=
"#sec21">Lower Level Methods are Easier to Customize
</a>
115 <a href=
"#sec22">Functional Where Possible
</a>
120 <a href=
"#sec23">Memoization
</a>
123 <a href=
"#sec24">Constant Shared Return Values
</a>
128 <a href=
"#sec25">Procedural Only Where Necessary
</a>
131 <a href=
"#sec26">Real World
</a>
136 <a href=
"#sec27">UCW and Arnesi
</a>
139 <a href=
"#sec28">CLSQL
</a>
142 <a href=
"#sec29">Elephant
</a>
149 <a href=
"#sec30">Sources and Further Reading
</a>
154 <a href=
"#sec31">Sources
</a>
159 <a href=
"#sec32">The Art of the Metaobject Protocol
</a>
162 <a href=
"#sec33">CLOS MOP Specification
</a>
165 <a href=
"#sec34">Metaobject Protocols: Why We Want Them and What Else They Can Do
</a>
168 <a href=
"#sec35">Why Are Black Boxes so Hard to Reuse?
</a>
173 <a href=
"#sec36">Further Reading
</a>
178 <a href=
"#sec37">A Metaobject Protocol for C++
</a>
181 <a href=
"#sec38">Open Implementations and Metaobject Protocols
</a>
186 <a href=
"#sec39">Software
</a>
191 <a href=
"#sec40">Closer to MOP
</a>
201 <!-- Page published by Emacs Muse begins here -->
202 <p>In Fall of
2006 I did a small project on Metaobject Protocols for my
203 CS
331 class. Here lie my notes which may perhaps be useful to
204 others. I hope to expand them into something more useful over time.
</p>
206 <h2><a name=
"sec1" id=
"sec1"></a>
209 <h3><a name=
"sec2" id=
"sec2"></a>
210 Object Protocols
</h3>
212 <p class=
"first">An object protocol is a set of methods and specification of the
213 interactions between the methods which provide some generic behavior
214 (e.g. of a sequence) that are then implemented by classes which
215 conform to the protocol (e.g. a vector or list). In most object
216 systems a class contains both the methods which implement a protocol
217 and the data used by the implementation. The intent is to emulate
218 state machines which pass messages between each other.
</p>
221 <h3><a name=
"sec3" id=
"sec3"></a>
224 <p class=
"first">The Common Lisp Object System (CLOS) is different. It separates
225 the data and method concepts into classes and generics. A class
226 contains data fields only, and a generic has methods specialized for
227 certain types attached to it. This seems a bit weird at first, but is
228 significantly more powerful as it encourages complete encapsulation
229 through its use of classes primarily for method specialization rather
230 than for state storage.
</p>
232 <h4><a name=
"sec4" id=
"sec4"></a>
233 Classes for Scratch Data and Types
</h4>
235 <p class=
"first">In CLOS classes store data in slots (which are the same as data
236 members). Encapsulation is not provided; any bit of code can use
237 <code>slot-value
</code> to access or set the value of a slot. This may seem odd at
238 first, but encapsulation is of questionable importance as the slots
239 are meant only to be used by the protocol defined around the class.
</p>
241 <p>Classes are defined with
<code>defclass
</code></p>
244 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">name
</span> (superclasses ...)
245 ((slot-name
<span class=
"emacs-face-builtin">:accessor
</span> slot-accessor ...)
249 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">example
</span> ()
250 ((foo
<span class=
"emacs-face-builtin">:accessor
</span> foo-of
<span class=
"emacs-face-builtin">:initform
</span> 5)))
252 (
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">example-child
</span> (example)
253 ((bar
<span class=
"emacs-face-builtin">:accessor
</span> bar-of
<span class=
"emacs-face-builtin">:initform
</span> (list
1 2 3))))
256 <p>Slot definitions have several options; the above example shows only the
257 <code>:accessor
</code> and
<code>:initform
</code> options which are the most commonly
258 used.
<code>:accessor
</code> generates an accessor for the slot (e.g. if you have
259 an instance of
<code>example
</code> you can
<code>(setf (foo-of some-example-instance)
260 'some-value)
</code> to set and
<code>(foo-of some-example-instance)
</code> to access the
261 value).
<code>:initform
</code> provides a default initial value for the slot as a
262 symbolic expression to be evaluated when an instance is created in the
263 lexical environment of the class definition.
</p>
266 <h4><a name=
"sec5" id=
"sec5"></a>
267 Generics with Methods that Implement Protocols
</h4>
269 <p class=
"first">Generics are like normal functions in Lisp, but they only provide a
270 lambda list (parameter list). Methods are added to the generic which
271 specialize on the types of their parameters and provide an
272 implementation. This allows writing rich layered protocols which can
273 enable selective modification of individual facets with minimal code.
</p>
276 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">generic
</span> (parameters ...)
279 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">generic-name
</span> ((parameter type) parameter ...)
280 <span class=
"emacs-face-doc">"documentation string"</span>
283 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">foo
</span> (bar baz quux)
284 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-doc">"Process the baz with the quux capacitor to make the
285 foo widget fly into the sky at warp speed"</span>))
287 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">foo
</span> ((bar example) baz (quux capacitor))
288 (launch bar (process-with quux baz)))
291 <p>A method lambda list differs from a normal lambda list only in that it
292 can specify the type of the parameter using the notation
<code>(name type)
</code>.
293 Note also that methods can specialize on the types of every
294 argument and not just the first one. This is quite powerful for
295 reasons outside of the scope of this presentation.
</p>
300 <h2><a name=
"sec6" id=
"sec6"></a>
301 Limitations of Default Language Behavior
</h2>
303 <p class=
"first">The behavior of a language is a compromise between many competing
304 issues that attempts to be as generally useful as possible so that
305 <em>most
</em> applications will have no issue with the default behavior. There
306 are, however, certain applications that could be cleanly written with
307 minor modifications to the behavior of the language, but would be
308 impossible or quite difficult to write otherwise.
</p>
310 <h3><a name=
"sec7" id=
"sec7"></a>
313 <p class=
"first">Most languages choose to preallocate storage for all of the slots of
314 an instance. Now imagine a contact database that stores information
315 about people in slots of a class. There may be dozens of slots, but
316 often many of them will be left blank. If slot storage is preallocated
317 much memory will be wasted and the database may not be able to fit
318 into the memory of the hardware it must run on (perhaps for financial
319 reasons, huge datasets, etc.).
</p>
321 <p>To save memory the author of the contact database must implement his
322 own system to store properties and allocate them lazily. This
323 represents a fair bit of effort, and would implement a system that
324 differed from the existing slot system of classes only regarding slot
327 <p>It would be useful if there were a way to customize slot allocation in
328 instances. The customizations would be minor and require overriding
329 only the initial allocation behavior and the behavior of the first
330 assignment to the slot. It is a a trivial problem in a language that
331 allows customization of these behaviors.
</p>
334 <h3><a name=
"sec8" id=
"sec8"></a>
337 <p class=
"first">Design Patterns are generalized versions of common patterns found in
338 programs. Many of them are merely methods to get around deficiencies
339 in the language, and can be quite messy to implement in some
340 languages. Ideally a pattern would be subsumed by the language, but
341 real world constraints require language standards to remain fairly
346 <h2><a name=
"sec9" id=
"sec9"></a>
349 <p class=
"first">Some types of programs could be written easily if the language were
350 customizable but are nearly impossible to write when it is not.
</p>
352 <h3><a name=
"sec10" id=
"sec10"></a>
353 Runtime Generated Classes
</h3>
355 <p class=
"first">Say you wanted to write a video game where players could create their
356 own objects, attach behaviors to the objects, and perhaps mix
357 different objects together to create new ones. When you abstract the
358 problem this looks just like an object system! Wouldn't it be nice if
359 your program could create new classes and methods on the fly portably?
</p>
362 <h3><a name=
"sec11" id=
"sec11"></a>
363 Object Inspection
</h3>
365 <p class=
"first">Imagine you were developing a complicated program with many different
366 objects that interacted in fairly complex ways. A tool to inspect the
367 structure of objects while debugging would be quite useful, but in a
368 traditional language would be impossible to implement portably. This
369 could force you to purchase a certain compiler implementation which
370 provided an inspector, and even then would likely not be customizable.
</p>
372 <p>This problem can be generalized to apply to most debugging tools; it
373 would be useful to write such tools portably because users of the
374 <em>language
</em> and not the
<em>compiler
</em> need to debug software. Sharing
375 infrastructure would result in better tools (more developers), and
376 save the man-years of wasted effort that comes with having to rewrite
377 unportable tools from scratch multiple times.
</p>
381 <h2><a name=
"sec12" id=
"sec12"></a>
382 Metaobject Protocols
</h2>
384 <h3><a name=
"sec13" id=
"sec13"></a>
385 Limited/Generalized Internals of the Implementation
</h3>
387 <p class=
"first">A Metaobject Protocol (MOP) is a generalized and limited subset of the
388 underlying language implementation. It is limited to allow multiple
389 implementation strategies; this, along with careful design, is
390 essential because programming language research is ever advancing and
391 new techniques for creating more reliable and faster implementations
392 are still being discovered.
</p>
394 <p>This subset of the implementation is exported as a set of methods on
395 metaobjects. Thus the language is implemented in itself. The system
396 can then be customized using the extension and overriding features of
397 the language itself.
</p>
400 <h3><a name=
"sec14" id=
"sec14"></a>
403 <h4><a name=
"sec15" id=
"sec15"></a>
406 <p class=
"first">A reflective MOP provides an interface to information
<em>about
</em> the
407 running system. It exposes class relationships, the methods attached
408 to a generic, etc. A reflective MOP often provides some functionality
409 for creating new classes at runtime. Smalltalk was one of the first
410 languages to expose a reflective MOP.
</p>
412 <h5>Example: Object Inspector
</h5>
415 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">example-inspect
</span> (instance)
416 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-doc">"Simple object inspector using CLOS MOP"</span>))
418 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">example-inspect
</span> ((instance t))
419 (format t
<span class=
"emacs-face-string">"Simple Object~% Value: ~S~%"</span> instance))
421 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">example-inspect
</span> ((instance standard-object))
422 (
<span class=
"emacs-face-keyword">let
</span> ((class (class-of instance)))
423 (format t
<span class=
"emacs-face-string">"Class: ~S, Superclasses: ~S~%"</span>
426 (class-precedence-list class)))
427 (
<span class=
"emacs-face-keyword">let
</span> ((slot-names (mapcar #'slot-definition-name
428 (class-slots class))))
429 (format t
<span class=
"emacs-face-string">"Slots: ~%~{ ~S~%~}"</span> slot-names)
430 (inspect-loop slot-names instance #'example-inspect))))
432 (
<span class=
"emacs-face-keyword">defun
</span> <span class=
"emacs-face-function-name">inspect-loop
</span> (slots instance inspector)
433 (format t
<span class=
"emacs-face-string">"Enter slot to inspect or :pop to go up one level: "</span>)
435 (
<span class=
"emacs-face-keyword">let*
</span> ((slot (read))
436 (found-slot (member slot slots)))
437 (
<span class=
"emacs-face-keyword">cond
</span> (found-slot
438 (funcall inspector (slot-value instance slot))
439 (funcall inspector instance))
440 ((eq slot
<span class=
"emacs-face-builtin">:pop
</span>) t)
442 (format t
<span class=
"emacs-face-string">"~S is invalid. Valid slot names: ~S~%"</span>
445 (inspect-loop slots instance inspector)))))
449 <h5>Example: Runtime Generated Classes and Methods
</h5>
453 <h4><a name=
"sec16" id=
"sec16"></a>
456 <p class=
"first">Intercessory MOPs allow the user to customize language behavior by
457 implementing methods which override certain aspects of the language
458 behavior. This class of MOPs are what make MOPs especially
459 powerful. No longer must a problem be restructured to fit the
460 implementation language; the underlying language can be reshaped to
461 fit the task at hand, and obfuscation of the intended structure of the
462 application can be avoided.
</p>
464 <h5>Example: Lazily Allocated Slots
</h5>
467 <h5>Example: Observer Design Pattern
</h5>
469 <p>A simple implementation of the observer pattern is under
100 lines,
470 and the user level code requires only a single line of code to make
471 any existing class observable.
</p>
473 <p>In a language lacking a MOP, implementing the observer pattern
474 requires modifying every accessor of a class to explicitly invoke any
475 observers, and necessitates the addition of a mixin class to the class
476 hierarchy. The fact that an object can be observed is a meta property
477 of the class, and forcing it to be implemented at the application
478 level dirties the inheritance hierarchy and adds unnecessary meta
479 details to the program.
</p>
482 <span class=
"emacs-face-comment-delimiter">;;;
</span><span class=
"emacs-face-comment">This metaclass adds a slot to instances which use it, and so the
483 </span><span class=
"emacs-face-comment-delimiter">;;;
</span><span class=
"emacs-face-comment">system is defined in its own package to avoid name conflicts
484 </span>(
<span class=
"emacs-face-keyword">defpackage
</span> <span class=
"emacs-face-type">:observer
</span>
485 (
<span class=
"emacs-face-builtin">:use
</span> <span class=
"emacs-face-builtin">:cl
</span> <span class=
"emacs-face-builtin">:c2mop
</span>)
486 (
<span class=
"emacs-face-builtin">:export
</span> observable register-observer unregister-observer))
488 (
<span class=
"emacs-face-keyword">in-package
</span> <span class=
"emacs-face-builtin">:observer
</span>)
490 <span class=
"emacs-face-comment-delimiter">;;;
</span><span class=
"emacs-face-comment">Metaclass
491 </span>(
<span class=
"emacs-face-keyword">defclass
</span> <span class=
"emacs-face-type">observable
</span> (standard-class)
493 (
<span class=
"emacs-face-builtin">:documentation
</span> <span class=
"emacs-face-doc">"Metaclass for observable objects"</span>))
495 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">compute-slots
</span> ((class observable))
496 <span class=
"emacs-face-doc">"Add a slot for storing observers to observable instances"</span>
497 (cons (make-instance 'standard-effective-slot-definition
498 <span class=
"emacs-face-builtin">:name
</span> 'observers
499 <span class=
"emacs-face-builtin">:initform
</span> '(make-hash-table)
500 <span class=
"emacs-face-builtin">:initfunction
</span> #'(
<span class=
"emacs-face-keyword">lambda
</span> () (make-hash-table)))
503 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">validate-superclass
</span> ((class observable)
504 (super standard-class))
507 (
<span class=
"emacs-face-keyword">defun
</span> <span class=
"emacs-face-function-name">register-observer
</span> (instance slot-name key closure)
508 (register-observer-with-class (class-of instance)
514 (
<span class=
"emacs-face-keyword">defun
</span> <span class=
"emacs-face-function-name">unregister-observer
</span> (instance slot-name key)
515 (unregister-observer-with-class (class-of instance)
520 (
<span class=
"emacs-face-keyword">defun
</span> <span class=
"emacs-face-function-name">get-observers
</span> (instance slot-name)
521 (get-observers-with-class (class-of instance)
525 (
<span class=
"emacs-face-keyword">defun
</span> <span class=
"emacs-face-function-name">add-observer-table
</span> (instance slot-name)
526 (setf (gethash slot-name (slot-value instance
530 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">register-observer-with-class
</span> (class instance slot-name key closure))
531 (
<span class=
"emacs-face-keyword">defgeneric
</span> <span class=
"emacs-face-function-name">unregister-observer-with-class
</span> (class
536 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">register-observer-with-class
</span> ((class observable)
542 (or (gethash slot-name
543 (slot-value instance 'observers))
544 <span class=
"emacs-face-comment-delimiter">;;
</span><span class=
"emacs-face-comment">Lazily add observer hash tables
545 </span> (add-observer-table instance slot-name)))
548 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">unregister-observer-with-class
</span> ((class observable)
552 (remhash key (gethash slot-name
553 (slot-value instance 'observers))))
555 (
<span class=
"emacs-face-keyword">defmethod
</span> <span class=
"emacs-face-function-name">get-observers-with-class
</span> ((class observable)
558 (gethash slot-name (slot-value instance 'observers)))
560 (
<span class=
"emacs-face-keyword">defmethod
</span> (
<span class=
"emacs-face-function-name">setf slot-value-using-class
</span>)
<span class=
"emacs-face-builtin">:before
</span> (new-value
564 (
<span class=
"emacs-face-keyword">let
</span> ((slot-name (slot-definition-name slot)))
565 (
<span class=
"emacs-face-keyword">if
</span> (not (eq 'observers slot-name))
566 (
<span class=
"emacs-face-keyword">let
</span> ((observers
567 (get-observers instance (slot-definition-name slot))))
568 (
<span class=
"emacs-face-keyword">if
</span> observers
569 (maphash #'(
<span class=
"emacs-face-keyword">lambda
</span> (key observer)
571 (
<span class=
"emacs-face-keyword">if
</span> (slot-boundp instance slot-name)
572 (slot-value instance slot-name)
582 <h3><a name=
"sec17" id=
"sec17"></a>
583 Violation of Encapsulation?
</h3>
585 <p class=
"first">A MOP may seem like a violation of encapsulation by revealing some
586 implementation details, but in reality a well designed protocol does
587 not reveal anything which was not already exposed. Implementation
588 decisions affect users, and some of these details do leak through to
589 higher levels (e.g. the memory layout of slots). Implicit in the
590 protocol specification are these implementation details, and the MOP
591 merely makes this limited subset available for customization.
</p>
593 <p>A MOP makes it possible to customize certain implementation decisions
594 that do not
<strong>radically
</strong> alter the behavior of the base language. The
595 conceptual vocabulary of the system retains its meaning, and so code
596 written in one dialect can interact with code written in another
597 without knowing that they speak different ones.
</p>
601 <h2><a name=
"sec18" id=
"sec18"></a>
602 MOP Design Principles
</h2>
604 <h3><a name=
"sec19" id=
"sec19"></a>
605 Layered Protocol
</h3>
607 <p class=
"first">A layered protocol design is good for both meta and normal object
608 protocols, and enables a combinatorial explosion of customizations to
611 <h4><a name=
"sec20" id=
"sec20"></a>
612 Top Level
<strong>Must
</strong> Call Lower Level Methods
</h4>
614 <p class=
"first">The top level methods of a layered protocol are required to call
615 certain lower level methods to perform some tasks. This both makes it
616 easier to customize the top level methods (which perform very broad
617 tasks) by providing some pieces of implementation for the programmer,
618 and enables more customization by opening up the replacement of lower
619 level functions as a way to alter a small detail of the high level
623 <h4><a name=
"sec21" id=
"sec21"></a>
624 Lower Level Methods are Easier to Customize
</h4>
626 <p class=
"first">The lower level methods of a MOP are limited in scope and can be
627 implemented easily. Often the desired changes to language behavior are
628 minor, and having methods that perform simple tasks which are often
629 customized reduces the effort required to extend the system.
</p>
633 <h3><a name=
"sec22" id=
"sec22"></a>
634 Functional Where Possible
</h3>
636 <p class=
"first">Functional protocols are preferred for MOPs (and object protocols in
637 general). Functional protocols open up several optimizations for the
638 implementation without burdening the user of the protocol.
</p>
640 <h4><a name=
"sec23" id=
"sec23"></a>
643 <p class=
"first">Memoization is the process of saving the results of a function call
644 for future use. This avoids expensive recomputation of values which
645 have not changed (recall that a true function will always return the
646 same result when given the same arguments).
</p>
648 <p>A functional MOP can be optimized easily by exploiting this property
649 to memoize the return values of calls to expensive operations. A MOP
650 must be be very fast to avoid making programs unusably slow, and
651 memoization is able to give an appreciable speedup in many cases
652 without a significant burden on memory usage.
</p>
655 <h4><a name=
"sec24" id=
"sec24"></a>
656 Constant Shared Return Values
</h4>
658 <p class=
"first">Disallowing modification of values returned by protocol methods allows
659 the implementation to return large data structures by reference to
660 avoid expensive copying without having to do expensive data integrity
661 checks or copying.
</p>
665 <h3><a name=
"sec25" id=
"sec25"></a>
666 Procedural Only Where Necessary
</h3>
668 <p class=
"first">Some operations like method invocation are inherently stateful and so
669 must use a procedural protocol. There is no benefit to be gained from
670 using a functional protocol, and indeed an attempt would result in
671 obtuse code that severely restricted the implementation. Do note that
672 only a very small part of method invocation is stateful (the actual
673 call), and most of it can be implemented functionally (e.g. computing
674 the discriminating function).
</p>
677 <h3><a name=
"sec26" id=
"sec26"></a>
680 <h4><a name=
"sec27" id=
"sec27"></a>
681 <a href=
"http://common-lisp.net/project/ucw/">UCW
</a> and
<a href=
"http://common-lisp.net/project/bese/arnesi.html">Arnesi
</a></h4>
683 <p class=
"first">Arnesi uses the CLOS MOP to implement methods which are transparently
684 rewritten into continuation passing style. This allows their execution
685 to be suspended at certain points and resumed later. UCW builds on top
686 of this to support a web framework where the statelessness of http is
687 hidden from the user; displaying a page suspends the execution of the
688 current continuation, and resumes it upon submission. The user level
689 code is completely unaware of this.
</p>
692 <h4><a name=
"sec28" id=
"sec28"></a>
693 <a href=
"http://clsql.b9.com">CLSQL
</a></h4>
695 <p class=
"first">CLSQL uses the reflective part of the CLOS MOP to map Common Lisp data
696 types into SQL types, and the intercessory protocol for slot
697 allocation to map slots onto database columns or sql expressions (for
698 implementing relational slots).
</p>
701 <h4><a name=
"sec29" id=
"sec29"></a>
702 <a href=
"http://common-lisp.net/project/elephant/">Elephant
</a></h4>
704 <p class=
"first">Elephant uses the CLOS MOP to transparently store any class to disk
705 and handle paging between the disk store and memory efficiently
706 without user intervention.
</p>
711 <h2><a name=
"sec30" id=
"sec30"></a>
712 Sources and Further Reading
</h2>
714 <h3><a name=
"sec31" id=
"sec31"></a>
717 <h4><a name=
"sec32" id=
"sec32"></a>
718 The Art of the Metaobject Protocol
</h4>
720 <h5>Kiczales, Gregor et al. MIT Press
1991</h5>
722 <p>Highly recommended reading even if you plan to never implement a MOP
723 or use the CLOS one. The design principles it recommends are quite
728 <h4><a name=
"sec33" id=
"sec33"></a>
729 <a href=
"http://www.lisp.org/mop/contents.html">CLOS MOP Specification
</a></h4>
731 <p class=
"first">Specification of the MOP for CLOS defined in
<em>The Art of the Metaobject Protocol
</em>.
</p>
734 <h4><a name=
"sec34" id=
"sec34"></a>
735 <a href=
"http://citeseer.ist.psu.edu/399658.html">Metaobject Protocols: Why We Want Them and What Else They Can Do
</a></h4>
737 <p class=
"first">A short overview of MOP design principles followed by three example
738 metaobject protocols for Scheme.
</p>
741 <h4><a name=
"sec35" id=
"sec35"></a>
742 <a href=
"http://www2.parc.com/csl/groups/sda/projects/oi/towards-talk/transcript.html">Why Are Black Boxes so Hard to Reuse?
</a></h4>
744 <p class=
"first">Transcription of a talk on the benefits of open implementations of
745 software. It first discusses several problems that black box software
746 implementations pose, and then presents existing solutions. It shows
747 how the existing solutions are insufficient, and then provides
748 metaobject protocols as a solution to most of the problems.
</p>
752 <h3><a name=
"sec36" id=
"sec36"></a>
755 <h4><a name=
"sec37" id=
"sec37"></a>
756 <a href=
"http://citeseer.ist.psu.edu/chiba95metaobject.html">A Metaobject Protocol for C++
</a></h4>
758 <p class=
"first">Example of a purely compile time MOP. It implements the functionality
759 of a code walker and something similar to the Lisp macro system.
</p>
762 <h4><a name=
"sec38" id=
"sec38"></a>
763 <a href=
"http://www.parc.com/csl/groups/sda/publications/papers/Kiczales-TUT95/for-web.pdf">Open Implementations and Metaobject Protocols
</a></h4>
765 <p class=
"first">It is a bit long, but it seems to follow a similar structure to AMOP
766 in introducing MOPs and their usefulness. The pages are slides with
767 notes, and so the
331 pages might not actually take that long to read.
</p>
771 <h3><a name=
"sec39" id=
"sec39"></a>
774 <h4><a name=
"sec40" id=
"sec40"></a>
775 <a href=
"http://common-lisp.net/project/closer/closer-mop.html">Closer to MOP
</a></h4>
777 <p class=
"first">Compatibility layer that attempts to present the
<em>Art of the Metaobject
778 Protocol
</em> MOP specification properly in as many Common Lisp
779 implementation as possible.
</p>
784 <!-- Page published by Emacs Muse ends here -->
786 <p class=
"cke-buttons">
787 <!-- validating badges, any browser, etc -->
788 <a href=
"https://validator.w3.org/check/referer"><img
789 src=
"https://www.w3.org/Icons/valid-xhtml10"
790 alt=
"Valid XHTML 1.0!" /></a>
792 <a href=
"https://www.anybrowser.org/campaign/"><img
793 src=
"img/buttons/w3c_ab.png" alt=
"[ Viewable With Any Browser
796 <a href=
"https://www.debian.org/"><img
797 src=
"img/buttons/debian.png" alt=
"[ Powered by Debian ]" /></a>
799 <a href=
"https://hcoop.net/">
800 <img src=
"img/buttons/hcoop.png"
801 alt=
"[ Hosted by HCoop]" />
804 <a href=
"https://www.fsf.org/register_form?referrer=114">
805 <img src=
"img/buttons/fsf_member.png"
806 alt=
"[ FSF Associate Member ]" />
810 <p class=
"cke-footer"><ascii_phil
> There once was a man named Bertold
811 <ascii_phil
> Who drank beer when the weather grew cold
812 <ascii_phil
> As he reached for his cup...
813 <ascii_phil
> "NEEEEVER GONNA GIVE YOU UP!!!"
814 <ascii_phil
> Oh, snap! You just got limerickrolled!
816 <p class=
"cke-timestamp">Last Modified: